#include<stdio.h>
#include<vector>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>
#include<unistd.h>

using namespace std;

vector<int> works;

sem_t sem;

void doWork(int work,pthread_t threadId)
{
	printf("threadId:%d,work id is %d\n",threadId,work);
}

void * thread(void *arg);

typedef struct ThreadPoolCThread
{
	void *cthread;
	void *threadPool;
} TPCT;

class CThread
{
	public:
		CThread(void* arg)
		{
			tpcp.cthread = this;
			tpcp.threadPool = arg;
			int res;
			res = pthread_create(&id,NULL,thread,&tpcp);
		}
		pthread_t getTID()
		{
			return id;
		}
	private:
		pthread_t id;
		TPCT tpcp;
};
class ThreadPool
{
	public:
		ThreadPool(void(*t_fun)(int,pthread_t),int count):_fun(t_fun)
		{
			sem_init(&semaphore,0,0);
			pthread_mutex_init(&mutexLock,NULL);

			for(int i = 0;i<count;i++)
			{
				CThread *thread = new CThread(this);
				threads.push_back(thread);
			}
		}
		void waitSem()
		{
			//printf("wait sem\n");
			sem_wait(&semaphore);
			//printf("wait sem_end\n");
			
		}
		void postSem()
		{
			//printf("post sem\n");
			sem_post(&semaphore);
		}
		void lockMutex()
		{
			pthread_mutex_lock(&mutexLock);
		}
		void unlockMutex()
		{
			pthread_mutex_unlock(&mutexLock);
		}
		void manageWork(int work,pthread_t tid)
		{
			(*_fun)(work,tid);
		}
	private:
		void(*_fun)(int,pthread_t);
		sem_t semaphore;
		pthread_mutex_t mutexLock;
		vector<CThread *> threads;
};


void* thread(void * para)
{
	while(1)
	{
		TPCT *tpcp = (TPCT *)para;
		ThreadPool *ins = (ThreadPool *)(tpcp->threadPool);
		CThread *ct = (CThread *)(tpcp->cthread);
		int nowWork;
		ins->waitSem();
		//sem_wait(&sem);
		//printf("thread wakeup\n");
		ins->lockMutex();
		if(works.empty())
		{
			printf("works is empty!\n");
			//sleep(1);
			continue;
		}
		nowWork = works.back();
		works.pop_back();
		ins->unlockMutex();
		ins->manageWork(nowWork,ct->getTID());
	}
	return NULL;
}

int main6()
{
	sem_init(&sem,0,0);
	ThreadPool *pool = new ThreadPool(doWork,7);
	for(int i = 0;i<10;i++)
	{
		works.push_back(i);
	}
	for(int j = 0;j<10;j++)
	{
		pool->postSem();
	}
	sleep(1);
	while(1)
	{
		if(works.size() <= 0)
		{
			works.push_back(rand());
			pool->postSem();
		}
		sleep(1);
	}
	return 0;
}
